home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / faxd / Class2Send.c++ < prev    next >
C/C++ Source or Header  |  1994-08-01  |  7KB  |  249 lines

  1. /*    $Header: /usr/people/sam/fax/faxd/RCS/Class2Send.c++,v 1.70 1994/04/14 04:12:44 sam Rel $ */
  2. /*
  3.  * Copyright (c) 1990, 1991, 1992, 1993, 1994 Sam Leffler
  4.  * Copyright (c) 1991, 1992, 1993, 1994 Silicon Graphics, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and 
  7.  * its documentation for any purpose is hereby granted without fee, provided
  8.  * that (i) the above copyright notices and this permission notice appear in
  9.  * all copies of the software and related documentation, and (ii) the names of
  10.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  11.  * publicity relating to the software without the specific, prior written
  12.  * permission of Sam Leffler and Silicon Graphics.
  13.  * 
  14.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  15.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  16.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  17.  * 
  18.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  19.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  20.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  22.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  23.  * OF THIS SOFTWARE.
  24.  */
  25. #include <stdio.h>
  26. #include "Class2.h"
  27. #include "ModemConfig.h"
  28.  
  29. /*
  30.  * Send Protocol for Class-2-style modems.
  31.  */
  32.  
  33. /*
  34.  * Status messages to ignore when dialing.
  35.  */
  36. static fxBool
  37. isNoise(const char* s)
  38. {
  39.     static const char* noiseMsgs[] = {
  40.     "CED",        // RC32ACL-based modems send this before +FCON
  41.     "DIALING",
  42.     "RRING",    // Telebit
  43.     "RINGING",    // ZyXEL
  44.     "+FHR:",    // Intel 144e
  45.     NULL
  46.     };
  47.  
  48.     for (u_int i = 0; noiseMsgs[i] != NULL; i++)
  49.     if (strneq(s, noiseMsgs[i], strlen(noiseMsgs[i])))
  50.         return (TRUE);
  51.     return (FALSE);
  52. }
  53.  
  54. /*
  55.  * Process the response to a dial command.
  56.  */
  57. CallStatus
  58. Class2Modem::dialResponse()
  59. {
  60.     ATResponse r;
  61.  
  62.     do {
  63.     /*
  64.      * Use a dead-man timeout since some
  65.      * modems seem to get hosed and lockup.
  66.      */
  67.     r = atResponse(rbuf, conf.dialResponseTimeout);
  68.     switch (r) {
  69.     case AT_ERROR:        return (ERROR);    // error in dial command
  70.     case AT_BUSY:        return (BUSY);    // busy signal
  71.     case AT_NOCARRIER:  return (NOCARRIER);    // no carrier detected
  72.     case AT_OK:        return (NOCARRIER);    // (for AT&T DataPort)
  73.     case AT_NODIALTONE: return (NODIALTONE);// local phone connection hosed
  74.     case AT_NOANSWER:   return (NOANSWER);    // no answer or ring back
  75.     case AT_FHNG:        return (NOANSWER);    // usually T1 timeout
  76.     case AT_FCON:        return (OK);    // fax connection
  77.  
  78.     case AT_TIMEOUT:            // timed out w/o response
  79.     case AT_CONNECT:            // modem thinks data connection
  80.         hangup();
  81.         break;
  82.     }
  83.     } while (r == AT_OTHER && isNoise(rbuf));
  84.     return (FAILURE);
  85. }
  86.  
  87. /*
  88.  * Process the string of session-related information
  89.  * sent to the caller on connecting to a fax machine.
  90.  */
  91. fxBool
  92. Class2Modem::getPrologue(Class2Params& dis, u_int& nsf, fxStr& csi, fxBool& hasDoc)
  93. {
  94.     fxBool gotParams = FALSE;
  95.     hasDoc = FALSE;
  96.     nsf = 0;
  97.     for (;;) {
  98.     switch (atResponse(rbuf, conf.t1Timer)) {
  99.     case AT_TIMEOUT:
  100.     case AT_EMPTYLINE:
  101.     case AT_NOCARRIER:
  102.     case AT_NODIALTONE:
  103.     case AT_NOANSWER:
  104.     case AT_ERROR:
  105.         processHangup("10");        // Unspecified Phase A error
  106.         return (FALSE);
  107.     case AT_FPOLL:
  108.         hasDoc = TRUE;
  109.         protoTrace("REMOTE has document to POLL");
  110.         break;
  111.     case AT_FDIS:
  112.         gotParams = parseClass2Capabilities(skipStatus(rbuf), dis);
  113.         break;
  114.     case AT_FNSF:
  115.         { const char* cp = skipStatus(rbuf);
  116.           nsf = fromHex(cp, strlen(cp));
  117.           protoTrace("REMOTE NSF \"%s\"", cp);
  118.         }
  119.         break;
  120.     case AT_FCSI:
  121.         csi = stripQuotes(skipStatus(rbuf));
  122.         recvCSI(csi);
  123.         break;
  124.     case AT_FHNG:
  125.         return (FALSE);
  126.     case AT_OK:
  127.         return (gotParams);
  128.     }
  129.     }
  130. }
  131.  
  132. void
  133. Class2Modem::sendBegin()
  134. {
  135.     // polling accounting?
  136. }
  137.  
  138. /*
  139.  * Initiate data transfer from the host to the modem when
  140.  * doing a send.  Note that some modems require that we
  141.  * wait for an XON from the modem in response to the +FDT,
  142.  * before actually sending any data.  This is not the case
  143.  * with most modems however, so whether or not we do this
  144.  * is a configuration parameter.
  145.  */
  146. fxBool
  147. Class2Modem::dataTransfer()
  148. {
  149.     return (vatFaxCmd(AT_NOTHING, "DT") &&
  150.     waitFor(AT_CONNECT, conf.pageStartTimeout) &&
  151.     (!conf.class2XmitWaitForXON || modemStopOutput()));
  152. }
  153.  
  154. /*
  155.  * Send the specified document using the supplied
  156.  * parameters.  The pph is the post-page-handling
  157.  * indicators calculated prior to intiating the call.
  158.  */
  159. fxBool
  160. Class2Modem::sendPhaseB(TIFF* tif, Class2Params& next, FaxMachineInfo& info,
  161.     fxStr& pph, fxStr& emsg)
  162. {
  163.     int ntrys = 0;            // # retraining/command repeats
  164.  
  165.     setDataTimeout(60, next.br);    // 60 seconds for 1024 byte writes
  166.     hangupCode[0] = '\0';
  167.  
  168.     fxBool transferOK;
  169.     fxBool morePages = FALSE;
  170.     do {
  171.     transferOK = FALSE;
  172.     if (abortRequested())
  173.          break;
  174.     /*
  175.      * Check the next page to see if the transfer
  176.      * characteristics change.  If so, update the
  177.      * current T.30 session parameters.
  178.      */
  179.     if (params != next) {
  180.         if (!class2Cmd(disCmd, next))
  181.         break;
  182.         params = next;
  183.     }
  184.     if (dataTransfer() && sendPage(tif)) {
  185.         /*
  186.          * Page transferred, process post page response from
  187.          * remote station (XXX need to deal with PRI requests).).
  188.          */
  189.         morePages = !TIFFLastDirectory(tif);
  190.         u_int ppm;
  191.         // XXX check pph length
  192.         switch (pph[0]) {
  193.         default:
  194.         morePages = FALSE;
  195.         emsg = "Unknown post-page-handling indicator \"" | pph | "\"";
  196.         /* fall thru... */
  197.         case 'P': ppm = PPM_EOP; break;
  198.         case 'M': ppm = PPM_EOM; break;
  199.         case 'S': ppm = PPM_MPS; break;
  200.         }
  201.         tracePPM("SEND send", ppm);
  202.         u_int ppr;
  203.         if (pageDone(ppm, ppr)) {
  204.         tracePPR("SEND recv", ppr);
  205.         switch (ppr) {
  206.         case PPR_MCF:        // page good
  207.         case PPR_PIP:        // page good, interrupt requested
  208.         case PPR_RTP:        // page good, retrain requested
  209.             countPage();
  210.             pph.remove(0);    // discard post-page-handling
  211.             ntrys = 0;
  212.             if (morePages) {
  213.             if (!TIFFReadDirectory(tif)) {
  214.                 emsg = "Problem reading document directory";
  215.                 break;
  216.             }
  217.             if (!sendSetupParams(tif, next, info, emsg))
  218.                 break;
  219.             }
  220.             transferOK = TRUE;
  221.             break;
  222.         case PPR_RTN:        // page bad, retrain requested
  223.             if (++ntrys >= 3) {
  224.             emsg = "Unable to transmit page"
  225.                    " (giving up after 3 attempts)";
  226.             transferOK = FALSE;
  227.             break;
  228.             }
  229.             morePages = TRUE;    // retransmit page
  230.             transferOK = TRUE;
  231.             break;
  232.         case PPR_PIN:        // page bad, interrupt requested
  233.             break;
  234.         }
  235.         }
  236.     }
  237.     } while (transferOK && morePages);
  238.     if (!transferOK) {
  239.     if (emsg == "") {
  240.         if (hangupCode[0])
  241.         emsg = hangupCause(hangupCode);
  242.         else
  243.         emsg = "Communication failure during Phase B/C";
  244.     }
  245.     abort();            // terminate session
  246.     }
  247.     return (transferOK);
  248. }
  249.